package rpc.frame.core.request;

import io.netty.channel.Channel;

import javax.annotation.PreDestroy;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 缓存 以及建立的连接 、
 * 避免重复建立Channel
 */
public class RpcRequestHolder {

    private static Map<String, RequestPromise> requestPromiseMap = new ConcurrentHashMap<String, RequestPromise>();
    private static Map<String,ChannelMapping> channelMappingMap=new ConcurrentHashMap<>();

    /**
     * 获取 requestPromise
     * @param requestId
     * @return
     */
    public static RequestPromise getRequestPromise(String requestId) {
        return requestPromiseMap.get(requestId);
    }

    /**
     * 添加 连接
     * @param requestId
     * @param requestPromise
     */
    public static void put(String requestId,RequestPromise requestPromise){
        requestPromiseMap.put(requestId,requestPromise);
    }

    /**
     *
     * @param requestId
     */
    public static void remove(String requestId){
        requestPromiseMap.remove(requestId);
    }

    /**
     * 往缓存中添加 channel 记录
     */
    public static void addChannel(ChannelMapping channelMapping){
        ChannelMapping mapping = channelMappingMap.get(channelMapping.getIpWithPort());
        if(mapping!=null){
           return;
        }
        channelMappingMap.put(channelMapping.getIpWithPort(),channelMapping);
    }

    /**
     * 获取根据IP地址和端口 获取 Channel
     *
     * @return
     */
    public static Channel getChannel(String serverIp, int serverPort){
        String ipWithPort = serverIp + ":" + serverPort;
        ChannelMapping channelMapping = channelMappingMap.get(ipWithPort);
        if(channelMapping!=null){
            return channelMapping.getChannel();
        }
        return null;
    }

    /**
     * 比对当前连接是否以及建立channel 了
     *
     * @param serverIp
     * @param serverPort
     * @return
     */
    public static boolean channelExist(String serverIp, int serverPort){
        return getChannel(serverIp,serverPort)!=null;
    }

    /**
     * 关闭某个网络连接
     * @param serverIp
     * @param serverPort
     */
    public static void removeChannel(String serverIp, int serverPort){
        String ipWithPort = serverIp + ":" + serverPort;
        ChannelMapping channelMapping = channelMappingMap.remove(ipWithPort);
        if(channelMapping!=null){
            Channel channel=channelMapping.getChannel();
            channel.closeFuture();
            channel.eventLoop().shutdownGracefully();
            channelMappingMap.remove(ipWithPort);
        }
    }


    /**
     * bean 销毁 关闭全部的channel
     */
    @PreDestroy
    public static void destroyAllChannel(){
        Collection<ChannelMapping> values = channelMappingMap.values();
        for(ChannelMapping mapping:values){
            mapping.getChannel().closeFuture();
            mapping.getChannel().eventLoop();
            channelMappingMap.remove(mapping.getIpWithPort());
        }
    }


}
